﻿using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Quartz.Impl;
using Quartz;
using CSRedis;
using System.Collections.ObjectModel;
using Castle.Core.Logging;
using Microsoft.Extensions.Logging;

namespace Hotel.Application.BackgroundServices
{
    public class UpdateRedisKeyBackgroundService : BackgroundService
    {
        private readonly ILogger<UpdateRedisKeyBackgroundService> logger;

        public UpdateRedisKeyBackgroundService(ILogger<UpdateRedisKeyBackgroundService> logger)
        {
            this.logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            ISchedulerFactory schedule = new StdSchedulerFactory();
            IScheduler scheduler = await schedule.GetScheduler();

            Job1.logger = logger;

            IJobDetail jobDetail1 = JobBuilder.Create<Job1>()
                .WithIdentity(nameof(Job1))
                .SetJobData(new JobDataMap
                {
                    { nameof(UpdateRedisKeyBackgroundService), logger }
                })
                .UsingJobData("hello", 0)
                .Build();

            IJobDetail jobDetail2 = JobBuilder.Create<Job2>()
                .WithIdentity(nameof(Job2))
                .Build();

            ITrigger trigger1 = TriggerBuilder.Create()
                .WithSimpleSchedule(o =>
                {
                    o.WithIntervalInSeconds(1).RepeatForever();
                })
                .WithIdentity(nameof(trigger1))
                .Build();

            ITrigger trigger2 = TriggerBuilder.Create()
                .WithSimpleSchedule(o =>
                {
                    o.WithIntervalInSeconds(1).WithRepeatCount(10);
                })
                .WithIdentity(nameof(trigger2))
            .Build();

            Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>> dic = new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>>
            {
                {
                    jobDetail1,
                    new List<ITrigger>
                    {
                        trigger1
                    }
                },
                {
                    jobDetail2,
                    new List<ITrigger>
                    {
                        trigger2
                    }
                }
            };

            await scheduler.ScheduleJob(jobDetail1, trigger1);
            await scheduler.Start();
        }
    }

    /// <summary>
    /// 作业
    /// </summary>
    [DisallowConcurrentExecution]   //当上一个任务未完成时，等待完成后再执行下一次，否则会产生并发
    [PersistJobDataAfterExecution]  //用于持久化JobData中的数据
    public class Job1 : IJob
    {
        public static ILogger<UpdateRedisKeyBackgroundService> logger { get; set; }

        public async Task Execute(IJobExecutionContext context)
        {
            //ILogger<UpdateRedisKeyBackgroundService> logger = context.JobDetail.JobDataMap[nameof(UpdateRedisKeyBackgroundService)] as ILogger<UpdateRedisKeyBackgroundService>;
            logger.LogInformation(DateTime.Now.ToString());

            int i = Convert.ToInt32(context.JobDetail.JobDataMap["hello"]);

            i++;

            //相当于重写JobData中的数据
            //如果不加持久化特性，则数据始终为1
            context.JobDetail.JobDataMap.Put("hello", i);

            logger.LogInformation($"+++++++{i}++++++++");
            
            CSRedisClient client = new CSRedisClient("localhost:6379,defaultDatabase=2");
            await Task.Delay(TimeSpan.FromSeconds(2));
        }
    }

    [DisallowConcurrentExecution]
    public class Job2 : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            CSRedisClient client = new CSRedisClient("localhost:6379,defaultDatabase=3");
            await client.LPushAsync("key:2", Guid.NewGuid());
        }
    }
}
